package com.andy.blog.common.utils.number;

import java.math.BigDecimal;

/**
 * 涉及高精度数值运算的工具类
 * Created by andy on 2023/2/21 17:24
 */
public class BigDecimalUtils {

    private BigDecimalUtils() {
    }

    /**
     * 价格、金额等字段保留小数点位数
     */
    public static final int SCALE_OF_MONEY = 2;

    /**
     * 根据单价和数量计算金额（金额=单价*数量），保留2位小数
     *
     * @param price
     * @param num
     * @return
     */
    public static BigDecimal multiply(BigDecimal price, int num) {
        return multiply(price, new BigDecimal(num));
    }

    public static BigDecimal multiply(BigDecimal price, BigDecimal num) {
        return multiply(price, num, SCALE_OF_MONEY);
    }

    public static BigDecimal multiply(BigDecimal price, BigDecimal num, int scale) {
        if (price == null || num == null) {
            return BigDecimal.ZERO;
        }
        return price.multiply(num).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }


    /**
     * 金额累加，处理null的情况，保留2位小数
     *
     * @param round
     * @param amount
     * @return
     */
    public static BigDecimal add(int round, BigDecimal... amount) {
        BigDecimal result = BigDecimal.ZERO;
        for (BigDecimal temp : amount) {
            result = result.add(temp == null ? BigDecimal.ZERO : temp);
        }
        return result.setScale(SCALE_OF_MONEY, round);
    }


    public static BigDecimal add(BigDecimal... amount) {
        return add(BigDecimal.ROUND_HALF_UP, amount);
    }

    /**
     * 金额相减，处理null的情况，保留2位小数
     *
     * @param amount1
     * @param amount2
     * @return
     */
    public static BigDecimal subtract(BigDecimal amount1, BigDecimal amount2) {
        BigDecimal amou1 = amount1 == null ? BigDecimal.ZERO : amount1;
        BigDecimal amou2 = amount2 == null ? BigDecimal.ZERO : amount2;

        return amou1.subtract(amou2).setScale(SCALE_OF_MONEY, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 金额除法运算
     *
     * @param amount1
     * @param amount2
     * @return
     */
    public static BigDecimal divide(BigDecimal amount1, BigDecimal amount2) {
        return divide(amount1, amount2, SCALE_OF_MONEY);
    }

    public static BigDecimal divide(BigDecimal amount1, Integer amount2) {
        return divide(amount1, BigDecimal.valueOf(amount2), SCALE_OF_MONEY);
    }

    public static BigDecimal divide(BigDecimal amount1, BigDecimal amount2, int scale) {
        if (amount1 == null || amount2 == null
                || amount1.compareTo(BigDecimal.ZERO) == 0
                || amount2.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        return amount1.divide(amount2, scale, BigDecimal.ROUND_HALF_UP);
    }

    public static BigDecimal valueOf(Double num) {
        if (num == null) {
            return null;
        }
        return new BigDecimal(String.valueOf(num)).setScale(SCALE_OF_MONEY, BigDecimal.ROUND_HALF_UP);
    }
}
